package drds.plus.sql_process.type.impl;

import drds.plus.sql_process.type.*;

import java.math.BigInteger;

/**
 * {@link BigInteger}类型
 */
public class BigIntegerType extends CommonType<BigInteger> {

    private static final BigInteger maxValue = BigInteger.valueOf(Long.MAX_VALUE);
    private static final BigInteger minValue = BigInteger.valueOf(Long.MIN_VALUE);
    private final Calculator calculator = new AbstractCalculator() {

        public Object doAdd(Object v1, Object v2) {
            BigInteger i1 = convert(v1);
            BigInteger i2 = convert(v2);
            return i1.add(i2);
        }

        public Object doSub(Object v1, Object v2) {
            BigInteger i1 = convert(v1);
            BigInteger i2 = convert(v2);
            return i1.subtract(i2);
        }

        public Object doMultiply(Object v1, Object v2) {
            BigInteger i1 = convert(v1);
            BigInteger i2 = convert(v2);
            return i1.multiply(i2);
        }

        public Object doDivide(Object v1, Object v2) {
            BigInteger i1 = convert(v1);
            BigInteger i2 = convert(v2);

            if (i2.equals(BigInteger.ZERO)) {
                return null;
            }

            return i1.divide(i2);
        }

        public Object doMod(Object v1, Object v2) {
            BigInteger i1 = convert(v1);
            BigInteger i2 = convert(v2);

            if (i2.equals(BigInteger.ZERO)) {
                return null;
            }

            return i1.remainder(i2);
        }
    };

    public int encode(Object value, byte[] bytes, int offset) {
        return Encoder.encodeBigInteger(this.convert(value), bytes, offset);
    }

    public int getLength(Object value) {
        if (value == null) {
            return 1;
        } else {
            return Encoder.calculateEncodedLength(convert(value).toString());
        }
    }

    public DecodeResult decode(byte[] bytes, int offset) {
        BigInteger[] bigIntegers = new BigInteger[1];
        int lenght = Decoder.decodeBigIntegerObject(bytes, offset, bigIntegers);
        return new DecodeResult(bigIntegers[0], lenght);
    }

    public BigInteger incr(Object value) {
        return convert(value).add(BigInteger.ONE);
    }

    public BigInteger decr(Object value) {
        return convert(value).subtract(BigInteger.ONE);
    }

    public BigInteger getMaxValue() {
        return maxValue;
    }

    public BigInteger getMinValue() {
        return minValue;
    }

    public Calculator getCalculator() {
        return calculator;
    }

    public int getSqlType() {
        return java.sql.Types.DECIMAL;
    }

}
